#ifndef COMMANDER_OLD_H
#define COMMANDER_OLD_H

#include <QObject>
#include <QSerialPort>
#include <QTimer>
#include <QVariant>

class CmdEle : public QObject
{
    Q_OBJECT
public:
    CmdEle(const QString& cmdName):m_strCmdName(cmdName),
        m_nDevId(cmdName.split("_").last().toInt()), m_nParam(0), m_nVisitCnt(0){}

    virtual ~CmdEle(){}
    QString getName();
    quint8* getCmd();

    // big motor
    void setCurrent1(float f);      // unit: mA   0~4955
    void setPos1(float f);          // unit: angle
    void setVelocity1(float f);     // 0~17000

    // small motor
    void setCurrent2(float f);      // unit: mA  0~4500
    void setPos2(float f);          // unit: angle
    void setVelocity2(float f);     /// 0~2920

    void incCount();
    quint8 count();

signals:

protected:
    virtual void buildCmd()=0;

    void getCrc16(quint8 *buff, quint8 bufLen, quint8 *buffOut);
    quint16 getCrc16(quint8 *buff, quint8 bufLen);
    void getCmd(quint8* buffIn, quint8 bufLen);

protected:
    quint8 m_buff[8];
    quint32 m_nParam;
    QString m_strCmdName;

private:
    quint8 m_nDevId;
    quint8 m_nVisitCnt;
};


class CmdStop1 : public CmdEle
{
    Q_OBJECT
public:
    CmdStop1() : CmdEle(tr("stop_1")) { buildCmd(); }

protected:
    void buildCmd();
};


class CmdStop2 : public CmdEle
{
    Q_OBJECT
public:
    CmdStop2() : CmdEle(tr("stop_2")) { buildCmd(); }

protected:
    void buildCmd();
};


class CmdReadPos1 : public CmdEle
{
    Q_OBJECT
public:
    CmdReadPos1() : CmdEle(tr("readpos_1")) { buildCmd(); }

protected:
    void buildCmd();
};

class CmdReadPos2 : public CmdEle
{
    Q_OBJECT
public:
    CmdReadPos2() : CmdEle(tr("readpos_2")) { buildCmd(); }

protected:
    void buildCmd();
};


class CmdReadCurrent1 : public CmdEle
{
    Q_OBJECT
public:
    CmdReadCurrent1() : CmdEle(tr("readcurrent_1")) { buildCmd(); }

protected:
    void buildCmd();
};


class CmdReadCurrent2 : public CmdEle
{
    Q_OBJECT
public:
    CmdReadCurrent2() : CmdEle(tr("readcurrent_2")) { buildCmd(); }

protected:
    void buildCmd();
};


class CmdReadVelocity1 : public CmdEle
{
    Q_OBJECT
public:
    CmdReadVelocity1() : CmdEle(tr("readvelocity_1")) { buildCmd(); }

protected:
    void buildCmd();
};


class CmdReadVelocity2 : public CmdEle
{
    Q_OBJECT
public:
    CmdReadVelocity2() : CmdEle(tr("readvelocity_2")) { buildCmd(); }

protected:
    void buildCmd();
};


class CmdReadVoltage1 : public CmdEle
{
    Q_OBJECT
public:
    CmdReadVoltage1() : CmdEle(tr("readvoltage_1")) { buildCmd(); }

protected:
    void buildCmd();
};



class CmdReadVoltage2 : public CmdEle
{
    Q_OBJECT
public:
    CmdReadVoltage2() : CmdEle(tr("readvoltage_2")) { buildCmd(); }

protected:
    void buildCmd();
};


class CmdWritePos1 : public CmdEle
{
    Q_OBJECT
public:
    CmdWritePos1() : CmdEle(tr("writepos_1")) { buildCmd(); }

protected:
    void buildCmd();
};


class CmdWritePos2 : public CmdEle
{
    Q_OBJECT
public:
    CmdWritePos2() : CmdEle(tr("writepos_2")) { buildCmd(); }

protected:
    void buildCmd();
};


class CmdWriteCurrent1 : public CmdEle
{
    Q_OBJECT
public:
    CmdWriteCurrent1() : CmdEle(tr("writecurrent_1")) { buildCmd(); }

protected:
    void buildCmd();
};


class CmdWriteCurrent2 : public CmdEle
{
    Q_OBJECT
public:
    CmdWriteCurrent2() : CmdEle(tr("writecurrent_2")) { buildCmd(); }

protected:
    void buildCmd();
};


class CmdWriteVelocity1 : public CmdEle
{
    Q_OBJECT
public:
    CmdWriteVelocity1() : CmdEle(tr("writevelocity_1")) { buildCmd(); }

protected:
    void buildCmd();
};


class CmdWriteVelocity2 : public CmdEle
{
    Q_OBJECT
public:
    CmdWriteVelocity2() : CmdEle(tr("writevelocity_2")) { buildCmd(); }

protected:
    void buildCmd();
};

class Repos1 : public CmdEle
{
    Q_OBJECT
public:
    Repos1() : CmdEle(tr("repos_1")) { buildCmd(); }

protected:
    void buildCmd();
};


class Repos2 : public CmdEle
{
    Q_OBJECT
public:
    Repos2() : CmdEle(tr("repos_2")) { buildCmd(); }

protected:
    void buildCmd();
};









class CommanderOld : public QObject
{
    Q_OBJECT
public:

    static CommanderOld& instance(QObject *parent = nullptr){
            static CommanderOld c(parent);
            return c;
        }

    int getAbsPos2() {return m_nAbsPos2;}

    void setSerialPort(QSerialPort* com);

protected:
    explicit CommanderOld(QObject *parent = nullptr);

signals:
    void sigMsg(QVariant msg);
    void sigVarValue(QVariant varValue);

public slots:

    void stop();
    void stop1();
    void stop2();
    void init();
    void repos();
    void toPos1(int n);
    void toPos2(int n);

    void jinxian();
    void jiajin();
    void qiege();
    void tuihui();

    void readI2();
    void readPos2();
    void readU1();

    void readI1();
    void readPos1();
    void readU2();

    void relativePos1(int pos);
    void relativePos2(int pos);

    void setCurrent1(int c);        // unit: mA, max to 4900mA
    void setCurrent2(int c);        // unit: mA, max to 4500mA
    void setVelocity1(int v);       // max to 17000
    void setVelocity2(int v);       // max to 2920

    void setQieGeCiShu(int c);


private slots:
    void onReadReady();
    void onStartCmd();
    void onGetParam();

    void onRecvCmdEleRes(QString cmdName, float f);

private:
    void startCmdTimer();

    void execCmd();

    quint16 getCrc16(quint8 *buff, quint8 bufLen);
    quint8 parseCmd(quint8 *buff, quint8 len);

    void initCmdNameMap();

private:
    QSerialPort* m_serialPort;
    QList<CmdEle*> m_listCmds;
    quint8 m_nDataIndex;
    QTimer* m_timerStartCmd;
    QTimer* m_timerGetParam;

    bool m_bBusy;
    QMap<quint8, QString> m_mapCmdName;

    int m_nAbsPos1;
    int m_nAbsPos2;

    int m_nQieGeCiShu;

    static CommanderOld* s_instance;
};

#endif // COMMANDER_OLD_H
